#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include "main.h"
#include "parser.h"
#include "symtab.h"
#include "pseudocode.h"

FILE *target;
int argcount = 0,prntTab = 0,genFlag = 0; //./mypas
char const *asmfile,*outfile;
int errFlag = 0;

int verifyExtension(char const *filename, char *extension){
  int i = strlen(extension);
  
  while(i > 0){
    if(filename[strlen(filename) - i] != extension[strlen(extension) - i]) return 0;
    i--;
  }
  
  return 1;
}

void about(void){
    fprintf(stdout, "\n\t\t   Mypas - Compilador de Pascal simplificado\n");
    fprintf(stdout, "\t\t     Disciplina: Compiladores -- Ano: 2012\n");
    fprintf(stdout, "\n\tUniversidade Estadual Paulista \"Júlio de Mesquita Filho\" (Unesp)\n");
    fprintf(stdout, "\t\t\t      Campus de Rio Claro\n");
    fprintf(stdout, "\n\nOrientação: Prof. Dr. Eraldo Pereira Marinho\n");
    fprintf(stdout, "\nAlunos:\n");
    fprintf(stdout, "\tMarcel Monzani Marum\n");
    fprintf(stdout, "\tPlínio Borges de Figueiredo\n");
    fprintf(stdout, "\tThales Eduardo Nazatto\n");
    fprintf(stdout, "\tTúlio de Siqueira Pereira\n\n");
    exit(0);
}

void help(void){
    fprintf(stdout, "\nInstruções:\n");
    fprintf(stdout, "\nExecutar com o comando \"./mypas [arquivo de entrada] [arquivo de saída]\"\n");
    fprintf(stdout, "O arquivo de entrada precisa estar com a extensão \"mypas\" e o arquivo de saída precisa estar com a extensão \"s\"\n");
    fprintf(stdout, "Caso algum dos arquivos (ou ambos) não sejam infomados, o compilador usará a entrada/saída padrão\n");
    fprintf(stdout, "\nAdicionais:\n");
    fprintf(stdout, "\nO comando \"./mypas -h\" mostra as instruções de uso\n");
    fprintf(stdout, "O comando \"./mypas -a\" mostra informações do programa e seus desenvolvedores\n\n");
    fprintf(stdout, "O comando \"./mypas -symtab [arquivo de entrada] [arquivo de saída]\" faz a compilação e mostra a tabela de símbolos do código utilizado\n\n");
    fprintf(stdout, "O comando \"./mypas -gen [arquivo de entrada] [arquivo de saída]\" faz apenas a geração de código\n\n");
    exit(0);
}

void flags(int argc, char const *argv[]){
  int endflags = 0;
  argcount++;
  while(!endflags){
    if(strcmp(argv[argcount],"-h") == 0){
      if(argc == 2){
	help();
      }else{
	fprintf(stderr, "ERROR: Command not supported\n");
	errFlag = PROGRAMERR;
      }
    }else if(strcmp(argv[argcount],"-a") == 0){
      if(argc == 2){
	about();
      }else{
	fprintf(stderr, "ERROR: Command not supported\n");
	errFlag = PROGRAMERR;
      }
    }else if(strcmp(argv[argcount],"-symtab") == 0){
      if(argc >= 2){
	prntTab = 1;
	argcount++;
      }else{
	fprintf(stderr, "ERROR: Command not supported\n");
	errFlag = PROGRAMERR;
      }
    }else if(strcmp(argv[argcount],"-gen") == 0){
      if(argc >= 2){
	genFlag = 1;
	argcount++;
      }else{
	fprintf(stderr, "ERROR: Command not supported\n");
	errFlag = PROGRAMERR;
      }
    }else{
      endflags = 1;
      argcount--;
    }
  }
}

void filein(int argc, char const *argv[]){
	argcount++;
	if(argcount < argc){
	  if (verifyExtension(argv[argcount],".mypas")){
	    tape = fopen(argv[argcount], "r");
	    if(tape == NULL) tape = stdin;
	  }else{
	    fprintf(stderr, "ERROR: Input file not supported (try files with \"mypas\" extension)\n");
	    errFlag = PROGRAMERR;
	  }
	}else{
	  tape = stdin;
	  argcount--;
	}
}

void fileout(int argc, char const *argv[]){
	argcount++;
	if(argcount < argc){
	  if (verifyExtension(argv[argcount],".s")){

	    target = fopen(argv[argcount], "w");
	    asmfile = argv[argcount];
	    
	    if(target == NULL) target = stdout;
	  }else{
	    fprintf(stderr, "ERROR: Output file not supported (try files with \"s\" extension)\n");
	    errFlag = PROGRAMERR;
	  }
	}else{
	  target = stdout;
	  argcount--;
	}
}

main(int argc, char const *argv[])
{  
    if (argc > 1){
	flags(argc,argv);
	filein(argc,argv);
	fileout(argc,argv);
    }else{
	tape = stdin;
	target = stdout;
    }

    lookahead = gettoken();
    
    program();
    
    printf("\n");

    if(!errFlag){
      concatgenasm();
      fprintf(target,"%s",genasm);
      
      fclose(tape);
      fclose(target);
      
      if(asmfile != NULL){
	FILE *procarq;
	char command[50];
	sprintf(command,"gcc -m32 %s -o %s",asmfile,programName);
	if ((procarq = popen(command,"r")) == NULL){
	  fprintf(stderr, "ERROR: Assembler failed\n");
	  errFlag = PROGRAMERR;
	  exit(-1);
	}
      }else if(!genFlag){
	fprintf(stderr, "WARNING: Compile not supported with stdout\n");
	errFlag = PROGRAMERR;
      }
      
      if(prntTab) print_symtab();
    }

    exit(0);
}
/*
pid_t pid = fork();
    char *args[10];
    if(pid == 0){
      args[0] = "as";
      args[1] = asmfile;
      args[2] = "-o";
      args[3] = "outfile.out";
      args[4] = NULL;
      
      execvp(args[0],args);
    }else{
      fprintf(stderr, "ERROR: Assembler failed!\n");
      exit(-1);
    }
    
    pid = fork();
    
    if(pid == 0){
      args[0] = "ld";
      args[1] = "outfile.out";
      args[2] = "-o";
      args[3] = "outprogram";
      args[4] = NULL;
      
      execvp(args[0],args);
    }else{
      fprintf(stderr, "ERROR: Linkage failed!\n");
      exit(-1);
    }
*/